'''
filename: job_func.py
author: yinwenlu
datetime: 2019/10/6 11:19
software: PyCharm
'''
import datetime
import threading

from sqlalchemy import or_

from cron import getmtShopBussinessStatus, ELESpider, geteleShopBussinessStatus, logger, updYseOrderInfo, traceback, \
    math, getYesOrderList, ShopMeituanInfo, ShopEleInfo
from db import Session, ShopBidding, ShopBiddingTarget, getAllEleShops, getAllMeituanShops, YesOrderInfo, BusinessInfo
from spider import MTSpider



def getYesOrderListJob(spideObj,shopId,**kwags):
    '''
    :param mt:
    :param type:
    :return:
    '''
    '''获取商店的平均出价'''

    '''获取订单使用的信息'''
    mins=kwags.get("mins")
    type=kwags.get("type")
    day=datetime.datetime.now().strftime("%Y-%m-%d")
    kwags.update({"day":day})
    if type==1:
        yestodayNum = spideObj.get_historyOrder()
        yestodayNum.sort()
        timelst = []
        for order in yestodayNum:
            timelst.append(order.split(' ')[1])
        dayperiod = {}
        i = 0
        j = 15
        index = 0
        a = 0
        while i < 24:
            while j <= 60:
                if j == 60:
                    j = 0
                    break
                else:
                    t = "%02d:%02d:00" % (i, j)
                    dayperiod[t] = 0
                    while index < len(timelst) and timelst[index] < t:
                        dayperiod[t] = dayperiod[t] + 1
                        index += 1
                    j += 15
            i += 1
        dayperiod["23:59:59"] = 0
        for tl in timelst:
            if tl > '23:45:00' and tl <= '23:59:59':
                a += 1
        dayperiod["23:59:59"] = a

        orderList = []  # 目前orderlist是96个
        for key, value in dayperiod.items():
            orderList.append(value)

        periodOrderList = []
        index = 0
        if mins == 30:
            # 将俩个俩个相加，变成48个
            while index <= 94:
                periodOrderList.append(orderList[index] + orderList[index + 1])
                index += 2
        elif mins == 60:
            while index <= 92:
                periodOrderList.append(
                    orderList[index] + orderList[index + 1] + orderList[index + 2] + orderList[index + 3])
                index += 4
        elif mins == 15:
            periodOrderList = orderList[:]
        kwags.update({"infoList": periodOrderList})
        updYseOrderInfo(shopId,type,**kwags)
        return True
    else:
        #2019-09-13T00:00:00"
        yesstart =day+"T00:00:00"
        yesend = day+"T23:59:59"
        yestodayNum = spideObj.getAllOrder(yesstart, yesend, 200)
        # print(yestodayNum)

        # 所有下单时间存进列表
        timelst = []
        for order in yestodayNum:
            # 2019-10-01T21:22:09,返回的时间是这样的，只取21:22:09
            timelst.append(order.get("activeTime").split('T')[1])
        timelst.reverse()
        dayperiod = {}
        i = 0
        j = 15
        index = 0
        a = 0
        while i < 24:
            while j <= 60:
                if j == 60:
                    j = 0
                    break
                else:
                    t = "%02d:%02d:00" % (i, j)
                    dayperiod[t] = 0
                    while index < len(timelst) and timelst[index] < t:
                        dayperiod[t] = dayperiod[t] + 1
                        index += 1
                    j += 15
            i += 1
        dayperiod["23:59:59"] = 0
        for tl in timelst:
            if tl > '23:45:00' and tl <= '23:59:59':
                a += 1
        dayperiod["23:59:59"] = a
        orderList = []  # 目前orderlist是96个
        for key, value in dayperiod.items():
            orderList.append(value)

        periodOrderList = []
        index = 0
        if mins == 30:
            # 将俩个俩个相加，变成48个
            while index <= 94:
                periodOrderList.append(orderList[index] + orderList[index + 1])
                index += 2
        elif mins == 60:
            while index <= 92:
                periodOrderList.append(
                    orderList[index] + orderList[index + 1] + orderList[index + 2] + orderList[index + 3])
                index += 4
        elif mins == 15:
            periodOrderList = orderList[:]
        kwags.update({"infoList": periodOrderList})
        updYseOrderInfo(shopId,type,**kwags)
        return True

def getTargetExposure(shopId, type, ct, dt):
    '''
    获取当前计划
    :param account:
    :param type:
    :param ct:
    :param dt:
    :return:
    '''
    try:
        ct=datetime.datetime.strptime(ct, "%Y-%m-%d %H:%M:%S")
        dt = datetime.datetime.strptime(dt, "%Y-%m-%d %H:%M:%S")
        session=Session()
        shopBiddingTarget=session.query(ShopBiddingTarget).filter(ShopBiddingTarget.shopId==shopId,ShopBiddingTarget.shopType==type,or_(ShopBiddingTarget.exposureTime==ct,ShopBiddingTarget.exposureTime==dt)).first()
        session.close()
        if not shopBiddingTarget:target=0
        else:target=shopBiddingTarget.newExposureNum
        return target
    except:
        print(traceback.format_exc())
        logger.warning(traceback.format_exc())


def getPeriodBiddingInfo(shopId,type,lastShopBidding,targetExposure,showCount,ct):
    '''
    获取上一次有效曝光的竞价信息
    :param shopId: 店铺的Id
    :param type: 店铺类型
    :param lastShopBidding: 上一次竞价记录
    :param targetExposure: 周期曝光量
    :param showCount: 当前的曝光量
    :param ct: 当前的时间
    :return:
    '''
    lastShowCount=lastShopBidding.exposureNum
    session=Session()
    lastShopBiddingId=session.query(ShopBidding.id).filter(ShopBidding.shopid==shopId,ShopBidding.shoptype==type,
                                                        ShopBidding.exposureNum<lastShowCount).order_by(ShopBidding.id.desc()).first()
    if not lastShopBiddingId:
        session.close()
        return 0
    lasterShopBidding=session.query(ShopBidding).filter(ShopBidding.shopid==shopId,ShopBidding.shoptype==type,
                                                        ShopBidding.id>lastShopBiddingId[0]).order_by(ShopBidding.id).first()
    session.close()
    periodTargetExposure=targetExposure-int(lasterShopBidding.targetNum)
    if lastShowCount!=int(lasterShopBidding.exposureNum):
        return False
    return periodTargetExposure

def getLastChangeBidding(shopId,type,exposure):
    '''
    获取距离上次曝光距离当前的时间
    :param shopId:
    :param type:
    :param exposure:
    :return:
    '''
    session=Session()
    lastChangeBidding = session.query(ShopBidding).filter(ShopBidding.shopid == shopId, ShopBidding.shoptype == type,
                                                             ShopBidding.exposureNum < exposure).order_by(
        ShopBidding.id.desc()).first()
    if lastChangeBidding:
        return lastChangeBidding
    else:
        return False

def getAllShops():
    '''
    获取所有符合竞价条件的店铺
    :return:
    '''
    shops = None

    mtShops = getAllMeituanShops()
    eleShops = getAllEleShops()
    if mtShops and eleShops:
        shops = mtShops+eleShops
    if not shops:
        return
    else:
        day=datetime.datetime.now().strftime("%Y-%m-%d")
        '''将获取到的店铺进行信息查询，然后进行信息存储
        将三组数据存入yesOrderInfo的head字段中
        1、访客数   2、平均出价  3、花费/预算'''
        yesterday = (datetime.datetime.now() + datetime.timedelta(days = -1)).strftime("%Y-%m-%d")
        ct = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:00")

        for shop in shops:
            thread = threading.Thread(target=saveData, args=(shop, day, yesterday, ct))
            thread.start()
def saveData(shop, day, yesterday, ct):
    """
    保存11点半的数据
    :param shop:
    :param day:
    :param yesterday:
    :param ct:
    :return:
    """
    try:
        account = shop.account

        cookies = shop.cookies
        shopType = shop.shopType
        spider = getSpider(cookies, shopType)
        headInfo = getSpecialHeadInfo(spider, shopType)
        headInfo['ep']['t'] = int(shop.targetExposure)  # 当天的目标曝光
        headInfo['cot']['x'] = int(shop.budget)  # 当天系统的预算
        updHeadInfoToYes(account, day, headInfo)

        if shopType == 1:
            getYesOrderList(spider, account, 30, 1, yesterday, ct)
        else:
            yes = (datetime.datetime.now() + datetime.timedelta(days=-1)).strftime("%Y-%m-%d")
            yesstart = yes + "T00:00:00"
            yesend = yes + "T23:59:59"
            getYesOrderList(spider, account, 30, 2, yesterday, ct, yesstart=yesstart, yesend=yesend)
    except:
        logger.debug(traceback.format_exc())
        logger.info(shop.account + "获取订单失败")
    try:
        infoList = getYesOrderInfo(account)
        orderList = [0 for i in range(48)]
        for t in infoList:
            if t and t[0]:
                t = eval(t[0])
                for i in range(48):
                    orderList[i] += t[i]
        setShopPercent(account, shopType, str(orderList))
    except:
        logger.debug(traceback.format_exc())
        logger.info(account + "更新percent失败")
    try:
        setShopBusyandIdleTime(account, shopType)
    except:
        logger.debug(traceback.format_exc())
        logger.info(account + "更新闲忙时段出错")




def getSpider(cookies,shopType):
    '''
    获取相应的爬虫对象
    :param cookies:
    :param shopType:
    :return:
    '''
    if shopType==1:
        spider=MTSpider(cookies)
    else:
        spider=ELESpider(cookies)
    return spider

def getSpecialHeadInfo(spider,shopType):
    '''
    pc获取平台的三部分信息，1、访客数   2、平均出价  3、花费/预算
    :param spider: 爬虫对象
    :param shopType: 店铺种类
    :return: dict
    '''
    if shopType==1:
        exposure = spider.gettodayExposure().get("data", {})
        clickCount = exposure.get("clickCount")
        showCount = exposure.get("showCount")
        currentCost = exposure.get("cost")
        avgPrice = exposure.get("avgPrice")
        avgSevenShopInfo = spider.getAvgSevenShopInfo()
        daysAvgClickCount = int(avgSevenShopInfo.get("clickCount", 0) / 7)
        #daysAvgCost = round(avgSevenShopInfo.get("cost") / 7, 2)
        #budget=None#获取当前的花费
        daysAvgPrice = avgSevenShopInfo.get("avgPrice", 0)

    else:
        exposure = spider.gettodayExposure().get('result', {})
        clickCount = exposure.get('uvCount', 0)
        showCount = exposure.get("totalExposureAmount", 0)
        currentCost = exposure.get("totalCost", 0)
        avgPrice = exposure.get("averageCost", 0)

        daysExposure = spider.get7DaysExposure()
        daysAvgClickCount = int(daysExposure.get("uvCount", 0) / 7)
        #daysAvgCost = int(daysExposure.get("totalCost", 0) / 7)
        #budget=None
        daysAvgPrice = daysExposure.get("averageCost", 0)
    exposure={"o":showCount,"t":None}
    click={"o":clickCount,"s":daysAvgClickCount}
    cost={"p":currentCost,"x":None}
    price={"o":avgPrice,"s":daysAvgPrice}
    specialHeadInfo={"ep":exposure,"ck":click,"cot":cost,"pc":price}
    return specialHeadInfo

def upYseOrderInfo(account,infoList,today,ct):
    '''
    添加最新的昨日订单信息
    :param account:
    :param infoList:
    :param ct:
    :return:
    '''
    try:
        yesOrderInfo=YesOrderInfo()
        yesOrderInfo.account=account
        yesOrderInfo.InfoList=str(infoList)
        yesOrderInfo.day=today
        yesOrderInfo.updatetime=ct
        session=Session()
        nowOrderInfo=session.query(YesOrderInfo).filter(YesOrderInfo.account==account,YesOrderInfo.day==today).first()
        if nowOrderInfo:
            nowOrderInfo.InfoList = str(infoList)
            nowOrderInfo.updatetime = ct
            session.commit()
            session.close()
        else:
            session.add(yesOrderInfo)
            session.commit()
            session.close()
    except:
        logger.warning(traceback.format_exc())
        return dict(code=500, message="fail", data=traceback.format_exc())

def updHeadInfoToYes(account,day,headInfo):
    '''
    将定时任务获取的头部信息更新到数据库
    :param account:
    :param day:
    :param headInfo:
    :return:
    '''
    headInfo=str(headInfo)
    session=Session()
    yesOrderInfo=session.query(YesOrderInfo).filter(YesOrderInfo.account==account,YesOrderInfo.day==day).first()
    if yesOrderInfo:
        yesOrderInfo.headInfo=headInfo
    else:
        session.add(YesOrderInfo(
            account=account,
            day=day,
            headInfo=headInfo,
        ))
    session.commit()
    session.close()

def setShopPercent(account,type,percent):
    session = Session()
    shop = None
    if type == 1:
        shop = session.query(ShopMeituanInfo).filter(ShopMeituanInfo.account == account).first()
    else:
        shop = session.query(ShopEleInfo).filter(ShopEleInfo.account == account).first()
    shop.percent = percent
    nowTime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    shop.updatetime = nowTime
    session.commit()
    session.close()

def setShopBusyandIdleTime(account,type):
    session = Session()
    shop = None
    if type == 1:
        shop = session.query(ShopMeituanInfo).filter(ShopMeituanInfo.account == account).first()
    else:
        shop = session.query(ShopEleInfo).filter(ShopEleInfo.account == account).first()
    percent = eval(shop.percent)
    specialTime = shop.specialtime
    rate = ''
    busyMaxPrice = 0
    busyMinPrice = 0
    idleMaxPrice = 0
    idleMinPrice = 0
    if specialTime is not None and specialTime != '':
        busy = eval(specialTime)
        for bztime in busy:
            if bztime.get("type") == 1:
                busyMaxPrice = bztime.get('p7')
                busyMinPrice = bztime.get('p6')
                rate = bztime.get('rate')
            else:
                idleMaxPrice = bztime.get('p7')
                idleMinPrice = bztime.get('p6')
                rate = bztime.get('rate')
        rate = float(rate) / 100
        s = sum(percent)
        busyTimeList = []
        idleTimeList = []
        busy = []
        idle = []
        for i in range(1, 49):
            if percent[i - 1] / s >= rate:
                busy.append(i)
            else:
                idle.append(i)
        bstart = busy[0]
        count = 0
        index = 0
        for i in range(len(busy) - 1):
            count += 1
            if busy[i] + 1 == busy[i + 1]:
                pass
            else:
                if count - index == 1:
                    busyTimeList.append({'s': getTimeByIndex(bstart - 1), 'e': getTimeByIndex(bstart)})
                    index = count
                    bstart = busy[i + 1]
                else:
                    bend = busy[i]
                    busyTimeList.append({'s': getTimeByIndex(bstart - 1), 'e': getTimeByIndex(bend)})
                    bstart = busy[i + 1]

        bend = busy[len(busy) - 1]
        busyTimeList.append({'s': getTimeByIndex(bstart - 1), 'e': getTimeByIndex(bend)})
        bstart = idle[0]
        count = 0
        index = 0
        for i in range(len(idle) - 1):
            count += 1
            if idle[i] + 1 == idle[i + 1]:
                pass
            else:
                if count - index == 1:
                    idleTimeList.append({'s': getTimeByIndex(bstart - 1), 'e': getTimeByIndex(bstart)})
                    index = count
                    bstart = idle[i + 1]
                else:
                    bend = idle[i]
                    idleTimeList.append({'s': getTimeByIndex(bstart - 1), 'e': getTimeByIndex(bend)})
                    bstart = idle[i + 1]
        bend = idle[len(idle) - 1]
        idleTimeList.append({'s': getTimeByIndex(bstart - 1), 'e': getTimeByIndex(bend)})
        for bt in busyTimeList:
            bt['type'] = 1
            bt['rate'] = str(rate * 100)
            bt['p1'] = '0.9'
            bt['p2'] = '0.9'
            bt['p3'] = '0.9'
            bt['p4'] = busyMinPrice
            bt['p6'] = busyMinPrice
            bt['p7'] = busyMaxPrice
            bt['p5'] = busyMaxPrice
        for bt in idleTimeList:
            bt['type'] = 2
            bt['rate'] = str(rate * 100)
            bt['p1'] = '0.9'
            bt['p2'] = '0.9'
            bt['p3'] = '0.9'
            bt['p4'] = idleMinPrice
            bt['p6'] = idleMinPrice
            bt['p7'] = idleMaxPrice
            bt['p5'] = idleMaxPrice
            busyTimeList.append(bt)
        shop.specialtime = str(busyTimeList)
        session.commit()
        session.close()

def getTimeByIndex(i):
    h = ""
    if i % 2 == 0:
        h = math.floor(i / 2)
        if h < 10:
            h = "0" + str(h) + ":00"
        else:
            h = str(h) +'' + ":00"
    else:
        h = math.floor(i / 2)
        if h < 10:
            h = "0" + str(h) + ":30"
        else:
            h = str(h) +'' + ":30"
    return h

def getYesOrderInfo(account):
    '''
    获取订单信息
    :param account:
    :return:
    '''
    try:
        session=Session()
        infiList=session.query(YesOrderInfo.InfoList).filter(YesOrderInfo.account==account).order_by(YesOrderInfo.id.desc())[0:7]
        session.close()
        if infiList:
            return infiList
        else: return []
    except:
        logger.warning(traceback.format_exc())
        return dict(code=500, message="fail", data=traceback.format_exc())

def getBiddingByTime(shopId, type, biddingTime):
    """
    获取当前账号的某一时间的竞价记录，获取其目标曝光以及实际曝光
    :param shopId:
    :param type:
    :param biddingTime:
    :return:
    """
    try:
        session=Session()
        targetNum, exposureNum = session.query(ShopBidding.targetNum, ShopBidding.exposureNum).filter(
            ShopBidding.shopid == shopId, ShopBidding.biddingTime == biddingTime, ShopBidding.shoptype == type).first()
        session.close()
        if targetNum and exposureNum:
            return targetNum,exposureNum
        else:
            return False,False
    except:
        logger.warning(traceback.format_exc())

def getBusinessInfo(spider):
    """
    获取当前账号的
    曝光数，访问数，推广消费，单词点击平均消费
    下单人数，入店转换率，下单转换率
    :param spider:
    :return:
    """
    trend_dict = {}
    thirty_day_dict = {}
    restOne = spider.getTrendList("7", "1")
    resultOne = restOne.get("flowChartsInfoList", None)
    if resultOne:
        for ro in resultOne:
            orderNum = ro.get("orderNum", -1)  # 下单人数
            visitRate = ro.get("visitRate", -1)  # 进店转换率
            orderRate = ro.get("orderRate", -1)  # 下单转换率
            day = ro.get("date", -1)  # 哪天的数据
            trend_dict[day] = {"orderNum": orderNum, "visitRate": visitRate, "orderRate": orderRate}
    restTwo = spider.getThirtyDayShopInfo()
    resultTwo = restTwo.get("history", None)
    if resultTwo:
        for ro in resultTwo:
            exposureNum = ro.get("showCount", -1)  # 曝光量
            avgPrice = ro.get("avgPrice", -1)  # 平均一次点击花费
            clickCount = ro.get("clickCount", -1)  # 访客数
            cost = ro.get("cost", -1)  # 当天的花费
            day = ro.get("time")  # 哪天的数据
            thirty_day_dict[day] = {"exposureNum": exposureNum, "avgPrice": avgPrice, "clickCount": clickCount,"cost":cost,
                                    "day": day}

    for key, value in thirty_day_dict.items():
        dict_mid = trend_dict.get(key, None)
        if dict_mid:
            thirty_day_dict[key] = dict(value, **dict_mid)

    return thirty_day_dict

def updBusinessInfo(business_list):
    """
    批量插入business_info中数据
    :param business_list:
    :return:
    """
    session = Session()
    try:
        session.add_all(business_list)
        rest = session.commit()
        session.close()
        return rest
    except:
        session.rollback()
        return False

def addBusinessInfo(shopId, shopType, cookies):
    """
    更新营业分析数据到数据库中
    :param shopId:
    :param shopType:
    :param cookies:
    :return:
    """
    try:
        spider = MTSpider(cookies)
        business_dict = getBusinessInfo(spider)
        business_list = []
        for key,value in business_dict.items():
            business_list.append(
                BusinessInfo(
                    shopId= shopId,
                    type = shopType,
                    day = value.get("day",None),
                    exposureNum = value.get("exposureNum", None),
                    clickNum = value.get("day",None),
                    cost = value.get("cost",None),
                    avgPrice = value.get("avgPrice",None),
                    orderNum = value.get("orderNum",None),
                    visitRate = value.get("visitRate",None),
                    orderRate = value.get("orderRate",None),
                )
            )

        rest = updBusinessInfo(business_list)
        if rest:
            return True
        else:
            return False
    except:
        return False

def getBusinessInfo(spider):
    """
    获取当前账号的
    曝光数，访问数，推广消费，单词点击平均消费
    下单人数，入店转换率，下单转换率
    :param spider:
    :return:
    """
    trend_dict = {}
    thirty_day_dict = {}
    restOne = spider.getTrendList("7", "1")
    resultOne = restOne.get("flowChartsInfoList", None)
    if resultOne:
        for ro in resultOne:
            orderNum = ro.get("orderNum", -1)  # 下单人数
            visitRate = ro.get("visitRate", -1)  # 进店转换率
            orderRate = ro.get("orderRate", -1)  # 下单转换率
            day = ro.get("date", -1)  # 哪天的数据
            trend_dict[day] = {"orderNum": orderNum, "visitRate": visitRate, "orderRate": orderRate}
    restTwo = spider.getThirtyDayShopInfo()
    resultTwo = restTwo.get("history", None)
    if resultTwo:
        for ro in resultTwo:
            exposureNum = ro.get("showCount", -1)  # 曝光量
            avgPrice = ro.get("avgPrice", -1)  # 平均一次点击花费
            clickCount = ro.get("clickCount", -1)  # 访客数
            cost = ro.get("cost", -1)  # 当天的花费
            day = ro.get("time")  # 哪天的数据
            thirty_day_dict[day] = {"exposureNum": exposureNum, "avgPrice": avgPrice, "clickCount": clickCount,"cost":cost,
                                    "day": day}

    for key, value in thirty_day_dict.items():
        dict_mid = trend_dict.get(key, None)
        if dict_mid:
            thirty_day_dict[key] = dict(value, **dict_mid)

    return thirty_day_dict

def updBusinessInfo(business_list):
    """
    批量插入business_info中数据
    :param business_list:
    :return:
    """
    session = Session()
    try:
        session.add_all(business_list)
        rest = session.commit()
        session.close()
        return rest
    except:
        session.rollback()
        return False

def addBusinessInfo(shopId, shopType, cookies):
    """
    更新营业分析数据到数据库中
    :param shopId:
    :param shopType:
    :param cookies:
    :return:
    """
    try:
        spider = MTSpider(cookies)
        business_dict = getBusinessInfo(spider)
        business_list = []
        for key,value in business_dict.items():
            business_list.append(
                BusinessInfo(
                    shopId= shopId,
                    type = shopType,
                    day = value.get("day",None),
                    exposureNum = value.get("exposureNum", None),
                    clickNum = value.get("clickCount",None),
                    cost = value.get("cost",None),
                    avgPrice = value.get("avgPrice",None),
                    orderNum = value.get("orderNum",None),
                    visitRate = value.get("visitRate",None),
                    orderRate = value.get("orderRate",None),
                )
            )
        rest = updBusinessInfo(business_list)
        return True
    except:
        return False